#include "HiranipraShared.h"

#include "HCM/IComponent.h"

#ifndef _SHARED_PLATFORM_GRAPHICS_VERTEXDECLARATION_H_
#define _SHARED_PLATFORM_GRAPHICS_VERTEXDECLARATION_H_

#define VERTEX_DECLARATION( var, elements ) VertexDeclaration var( elements, sizeof( elements ) / sizeof( VertexElement ) );

namespace Hiranipra {
	namespace Platform {
		namespace Graphics {

			enum VertexElementFormat
			{
				VertexFormatSingle,
				VertexFormatVector2,
				VertexFormatVector3,
				VertexFormatVector4,
				VertexFormatColor,
				VertexFormatRgba32,
				VertexFormatByte4,
				VertexFormatShort2,
				VertexFormatShort4,
			};

			enum VertexElementUsage
			{
				VertexUsagePosition,
				VertexUsageNormal,
				VertexUsageTextureCoordinate,
				VertexUsageColor,
				VertexUsageBlendWeight,
				VertexUsageBlendIndices,
				VertexUsagePointSize,
				VertexUsageTangent,
				VertexUsageBinormal,
				VertexUsageDepth,
				VertexUsageSample,
			};

			typedef struct VertexElement_t
			{
			public:
				VertexElement_t( const VertexElementFormat format, const VertexElementUsage usage ) :
				  Format( format ), Usage( usage )
				{
				}

				VertexElementFormat		Format;
				VertexElementUsage		Usage;
				uint32					Index;
				uint32					Offset;
				uint32					Count;

				uint32 GetCount() const
				{
					switch( Format )
					{
					default:						return 0;
					case VertexFormatSingle:		return 1;
					case VertexFormatVector2:		return 2;
					case VertexFormatVector3:		return 3;
					case VertexFormatVector4:		return 4;
					case VertexFormatRgba32:		return 4;
					case VertexFormatByte4:			return 4;
					case VertexFormatShort2:		return 2;
					case VertexFormatShort4:		return 4;
					};
				}
				
				uint32 GetSize() const
				{
					switch( Format )
					{
					default:						return 0;
					case VertexFormatSingle:		return sizeof( float );
					case VertexFormatVector2:		return sizeof( float ) * 2;
					case VertexFormatVector3:		return sizeof( float ) * 3;
					case VertexFormatVector4:		return sizeof( float ) * 4;
					case VertexFormatRgba32:		return 4;
					case VertexFormatByte4:			return 4;
					case VertexFormatShort2:		return sizeof( short ) * 2;
					case VertexFormatShort4:		return sizeof( short ) * 4;
					};
				}

			public:
				uint32		InternalTag1;
				uint32		InternalTag2;
			} VertexElement;

			typedef struct VertexDeclaration_t
			{
			public:
				VertexDeclaration_t( VertexElement* elements, uint32 count ) :
					_size( 0 )
				{
					for( uint32 n = 0; n < count; n++ )
						this->Add( elements[ n ] );
				}

				vector<VertexElement>	Elements;

				void Add( VertexElement& element )
				{
					element.Index = this->Elements.size();
					element.Offset = _size;
					element.Count = element.GetCount();
					_size += element.GetSize();
					this->Elements.push_back( element );
				}

				uint32 GetStrideSize() const { return _size; }

			public:
				uint32		InternalTag;

			private:
				uint32		_size;
			} VertexDeclaration;

		}
	}
}

#endif // _SHARED_PLATFORM_GRAPHICS_VERTEXDECLARATION_H_
